from flask import abort, jsonify
from flask import current_app
from flask import request
from flask import session,g
from info import constants, db
from info.models import User, News, Comment, CommentLike
from info.moduls.news import news_bp
from flask import render_template
from info.utils.common import get_user_info
from info.utils.response_code import RET

@news_bp.route("/comment_like", methods=["POST"])
@get_user_info
def set_comment_like():
    """评论点赞接口"""
    # 1. 获取参数
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg="用户未登录")

    param_dict = request.json
    news_id = param_dict.get("news_id")
    comment_id = param_dict.get("comment_id")
    action = param_dict.get("action")

    # 2. 校验参数
    if not all([news_id, comment_id, action]):
        return jsonify(errno=RET.NODATA, errmsg="参数为空")

    if action not in ["add", "remove"]:
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    try:
        news_id = int(news_id)
        comment_id = int(comment_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg="参数错误")

    # 3.逻辑处理
    # 3.1 评论是否存在
    try:
        comment = Comment.query.get(comment_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="查询评论数据库异常")
    if not comment:
        return jsonify(errno=RET.NODATA, errmsg="评论数据为空")

    # 3.2 判断action是点赞还是取消点赞
    if action == "add":
        comment_like_model = CommentLike.query.filter(CommentLike.user_id == user.id, CommentLike.comment_id == comment_id).first()
        if not comment_like_model:
            # 点赞
            comment_like_model = CommentLike()
            comment_like_model.user_id = user.id
            comment_like_model.comment_id = comment_id
            db.session.add(comment_like_model)
            # 评论模型点赞数累加
            comment.like_count += 1

    else:
        # 取消点赞
        comment_like_model = CommentLike.query.filter(CommentLike.user_id == user.id, CommentLike.comment_id == comment_id).first()
        if comment_like_model:
            db.session.delete(comment_like_model)
            # 评论模型点赞数减一
            comment.like_count -= 1

    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="添加评论点赞模型到数据库异常")

    return jsonify(errno=RET.OK, errmsg="OK")



@news_bp.route("/news_comment", methods=["POST"])
@get_user_info
def add_news_comment():
    """添加新闻评论"""

    # 1. 获取参数
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg="用户未登录")
    param_dict = request.json
    news_id = param_dict.get("news_id")
    comment = param_dict.get("comment")
    # 有值：表示对parent_id这条评论进行回复了， 没有值：评论的是新闻
    parent_id = param_dict.get("parent_id")

    # 2. 校验参数
    if not all([news_id, comment]):
        return jsonify(errno=RET.NODATA, errmsg="参数为空")

    try:
        news_id = int(news_id)
        if parent_id:
            parent_id = int(parent_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg="参数错误")

    # 3. 逻辑处理
    # 3.1 根据news_id 判断要评论的新闻是否存在
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="查询新闻对象数据库异常")
    if not news:
        return jsonify(errno=RET.NODATA, errmsg="新闻对象数据为空")
    # 3.2 创建评论对象
    comment_obj = Comment()
    comment_obj.user_id = user.id
    comment_obj.news_id = news_id
    comment_obj.content = comment
    if parent_id:
        comment_obj.parent_id = parent_id

    # 由于返回值里面需要调用comment_obj.to_dict()，所以在调用之前需要将数据提交到数据库，所以还是要写commit
    try:
        db.session.add(comment_obj)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg="保存评论数据异常")


    # 4. 返回值
    return jsonify(errno=RET.OK, errmsg="评论成功", data=comment_obj.to_dict())



@news_bp.route("/news_collect", methods=["POST"])
@get_user_info
def collect_news():
    """收藏/取消收藏 新闻"""

    # 1.获取参数
    param_dict = request.json
    news_id = param_dict.get("news_id")
    action = param_dict.get("action")
    user = g.user

    # 2.参数校验
    if not news_id:
        return jsonify(errno=RET.PARAMERR, errmsg="参数不完整")
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg="用户未登录")
    if action not in ["cancel_collect", "collect"]:
        return jsonify(errno=RET.PARAMERR, errmsg="参数传递错误")

    # 3.逻辑处理
    # 3.1 根据新闻id查询新闻
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        jsonify(errno=RET.DBERR, errmsg="查询新闻数据异常")

    if not news:
        jsonify(errno=RET.NODATA, errmsg="新闻数据为空")

    # 3.2 收藏和取消收藏
    if action == "collect":
        # 收藏新闻 将新闻添加到用户收藏列表
        user.collection_news.append(news)
    else:
        # 取消收藏新闻 将新闻从到用户收藏列表移除
        user.collection_news.remove(news)

    try:
        # 数据库提交操作
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        # 数据库回滚操作
        db.session.rollback()
        jsonify(errno=RET.DBERR, errmsg="数据库提交失败")

    # 4.返回值处理
    return  jsonify(errno=RET.OK, errmsg="OK")



# 127.0.0.1:5000/news/2
@news_bp.route("/<int:news_id>")
@get_user_info
def detail_news(news_id):

    # 1.获取用户
    user = g.user

    # 2 新闻点击排行榜的逻辑
    # [news1,news2....]
    newsobj_list = News.query.order_by(News.clicks.desc()).limit(constants.CLICK_RANK_MAX_NEWS)
    # 字典列表里面装着新闻排行的数据

    news_click_list = []
    if newsobj_list:
        for news in newsobj_list:
            news_click_list.append(news.to_basic_dict())

    # 3.获取新闻数据的具体内容
    news = None
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        abort(404)
    # 获取新闻数据失败
    if not news:
        abort(404)
    # TODO: 浏览量累加
    news.clicks += 1
    
    # 标示用户是否有收藏该条新闻 当为：False 表示用户未收藏 反之
    is_collected = False
    # 判断用户是否登录
    if g.user:
        # 判断该新闻是否被用户收藏
        if news in g.user.collection_news.all():
            is_collected = True

    # 查询评论数据
    comments = []
    try:
        comments = Comment.query.filter(News.id == news.id).order_by(Comment.create_time.desc()).all()
    except Exception as e:
        current_app.logger.error(e)

    comment_like_id_list = []
    if user:
        try:
            # 查询当前用户对这个条新闻的评论那几条点过赞
            # 1.查询出当前新闻的所有评论，取得所有评论的id —>  [1,2,3,4,5]
            comment_id_list = [comment.id for comment in comments]
            # 2.再通过评论点赞模型(CommentLike)查询当前用户点赞了那几条评论  —>[模型1,模型2...]
            comment_like_list = CommentLike.query.filter(CommentLike.comment_id.in_(comment_id_list), CommentLike.user_id == user.id).all()
            # 3. 通过上一步的模型列表，获取所以点赞过的评论id
            comment_like_id_list = [comment_like_model.comment_id for comment_like_model in comment_like_list]
        except Exception as e:
            current_app.logger.error(e)

    news_comment_li = []
    if comments:
        for comment in comments:
            comment_dict = comment.to_dict()
            comment_dict["is_like"] = False # 查询??
            # 如果评论id在评论的点赞id内，表示用户点过这条评论的赞
            if comment.id in comment_like_id_list:
                comment_dict["is_like"] = True
            news_comment_li.append(comment_dict)

    data = {
        "user": g.user.to_dict() if g.user else None,
        "news_click_list": news_click_list,
        "news": news.to_dict(),
        "is_collected": is_collected,
        "comments": news_comment_li
    }
    return render_template("detail.html",data=data)